Many systems use a server-based computing model, such as a virtual desktop infrastructure (VDI) to provide complete, centrally-managed desktops to users using computer virtualization technology. The VDI is used to create large numbers of independent computing environments for large numbers of users. In a typical VDI architecture, user displays and input devices are local, but applications execute remotely in a server. As such, a virtual desktop may be accessible by one or more remote users through a network. The virtual desktop may mimic a desktop computer interface or an interface of another computer or system by providing a virtual screen or virtual display to an end user. A protocol, such as an application programming interface (API), may be used to integrate VDI software components with other products. For example, a VDI operating system component may implement an API to provide an interface with third-party vendor applications such as a custom multi-pathing plugin or device driver for a storage vendor's storage devices.
To ensure that they work adequately and meet a predefined threshold level for quality, APIs need to be tested. Some commonly known testing techniques can be used to test APIs. For example, unit testing, a method used to test individual units of source code, can be used to call APIs with various inputs and validate the resulting outputs. Functional or system testing, which invokes APIs indirectly by running workloads from user space, can also be used to test APIs. Function testing has the advantage of more closely resembling the manner in which users actually use the system.
However, there are limitations to existing testing techniques. For example, various categories of APIs, such as those that may generate failure responses based on the status of other system components, may be difficult to verify with unit tests because unit tests are, by definition, limited to testing individual units of source code. Even if unit tests could handle these types of APIs, a variety of real storage devices may be difficult to procure for testing environments, and staging specific error events or conditions within each of those proprietary storage devices may be difficult or impossible. Functional or system testing approaches are also limited because it may be difficult, if not impossible, for them to call and examine the response to lower-level, kernel APIs by running user space workloads. Finally, error handling code is often tested poorly, as error conditions are difficult to generate deterministically.